/**
 * @file asdu_parser.c
 * @brief ASDU解析器实现
 * @details 本文件实现了104协议的ASDU解析器功能，包括通用ASDU解析、遥信数据ASDU
 *          解析、遥测数据ASDU解析、控制命令ASDU解析、系统命令ASDU解析、ASDU验证、
 *          信息提取等核心功能。支持多种数据类型的信息对象解析，确保解析的ASDU数据
 *          符合104协议规范，包含完整的错误处理和参数验证。
 * 
 * @author zyb
 * @date 2025-10-07
 * @version 1.0
 * 
 * @note ASDU解析时需要验证类型标识和信息对象数据的匹配性
 * @warning 解析后的信息对象数据指针指向原始缓冲区，不需要单独释放
 * 
 * @see asdu_parser.h
 * @see protocol_types.h
 * @see constants.h
 * @see error_codes.h
 */

#include "asdu_parser.h"
#include "../../common/types/include/protocol_types.h"
#include "../../common/types/include/constants.h"
#include "../../common/error/include/error_codes.h"
#include "../../common/utils/include/validation_utils.h"
#include "../../../../../common/utils/include/buffer_utils.h"
#include "../../../../../common/logs/include/logger.h"
#include <string.h>
#include <stdio.h>

// 定义模块名称
#define LOG_MODULE_NAME "ASDU_PARSER"

/* ==================== 通用ASDU解析函数实现 ==================== */

/**
 * @brief 解析ASDU头部
 * @details 从字节流中解析ASDU头部信息，包括类型标识、可变结构限定词、
 *          传送原因、公共地址等字段。这是ASDU解析的第一步，用于获取
 *          ASDU的基本信息和结构信息。
 * 
 * @param buffer 输入缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小，必须至少为ASDU_HEADER_SIZE
 * @param asdu ASDU结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 解析成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_ASDU_INVALID_TYPE: 无效类型标识
 * 
 * @note 此函数只解析ASDU头部，不解析信息对象数据
 * @warning 解析后的ASDU结构需要进一步解析信息对象数据
 * 
 * @see asdu_t
 * @see ASDU_HEADER_SIZE
 * @see parse_asdu_info_objects
 */
protocol_error_t parse_asdu_header(const uint8_t* buffer, size_t buffer_size, asdu_t* asdu) {
    LOG_DEBUG(LOG_MODULE_NAME, "解析ASDU头部: buffer=%p, buffer_size=%zu, asdu=%p", 
              buffer, buffer_size, asdu);
    
    if (buffer == NULL || asdu == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    if (buffer_size < ASDU_HEADER_SIZE) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: %zu < %d", buffer_size, ASDU_HEADER_SIZE);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "开始解析ASDU头部，缓冲区大小: %zu", buffer_size);
    
    // 打印原始数据（前16字节）
    LOG_DEBUG(LOG_MODULE_NAME, "========== ASDU原始数据（前16字节）==========");
    int print_len = (buffer_size < 16) ? buffer_size : 16;
    char hex_str[128] = {0};
    int hex_len = 0;
    for (int i = 0; i < print_len && hex_len < 127; i++) {
        hex_len += snprintf(hex_str + hex_len, 128 - hex_len, "%02X ", buffer[i]);
    }
    LOG_DEBUG(LOG_MODULE_NAME, "原始数据: %s", hex_str);
    LOG_DEBUG(LOG_MODULE_NAME, "===========================================");
    
    size_t offset = 0;
    
    /* 解析类型标识 */
    LOG_DEBUG(LOG_MODULE_NAME, "========== ASDU字节[%zu]: 类型标识 ==========", offset);
    protocol_error_t result = buffer_error_to_protocol_error(buffer_read_u8(buffer, offset++, &asdu->type_id));
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "读取类型标识失败: %d", result);
        return result;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "字节值: 0x%02X (%d)", asdu->type_id, asdu->type_id);
    LOG_DEBUG(LOG_MODULE_NAME, "含义: ASDU类型标识，标识信息对象的类型");
    LOG_DEBUG(LOG_MODULE_NAME, "说明: 常见类型 - 1=M_SP_NA_1(单点信息), 3=M_DP_NA_1(双点信息), 13=M_ME_NB_1(测量值), 45=C_SC_NA_1(单点命令)");
    LOG_DEBUG(LOG_MODULE_NAME, "当前类型: %d", asdu->type_id);
    
    /* 解析可变结构限定词 */
    LOG_DEBUG(LOG_MODULE_NAME, "========== ASDU字节[%zu]: 可变结构限定词 ==========", offset);
    uint8_t vsq_byte;
    result = buffer_error_to_protocol_error(buffer_read_u8(buffer, offset++, &vsq_byte));
    if (result != PROTOCOL_SUCCESS) {
        return result;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "字节值: 0x%02X (%d)", vsq_byte, vsq_byte);
    LOG_DEBUG(LOG_MODULE_NAME, "含义: 可变结构限定词，包含信息对象数量和结构限定符");
    asdu->vsq.sq = (vsq_byte >> 7) & 0x01;
    asdu->vsq.number_of_objects = vsq_byte & 0x7F;
    LOG_DEBUG(LOG_MODULE_NAME, "bit7 (SQ): %d - %s", asdu->vsq.sq, 
             asdu->vsq.sq ? "连续结构(信息对象地址连续)" : "非连续结构(信息对象地址不连续)");
    LOG_DEBUG(LOG_MODULE_NAME, "bit0-6 (数量): %d - 信息对象数量", asdu->vsq.number_of_objects);
    
    /* 解析传送原因 */
    LOG_DEBUG(LOG_MODULE_NAME, "========== ASDU字节[%zu-%zu]: 传送原因 ==========", offset, offset+1);
    result = buffer_error_to_protocol_error(buffer_read_u16(buffer, offset, (uint16_t*)&asdu->cause_of_transmission, 1)); /* 大端序 */
    if (result != PROTOCOL_SUCCESS) {
        return result;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "字节值: 0x%02X 0x%02X (%d)", 
             buffer[offset], buffer[offset+1], asdu->cause_of_transmission);
    LOG_DEBUG(LOG_MODULE_NAME, "含义: 传送原因，2字节，大端序");
    LOG_DEBUG(LOG_MODULE_NAME, "说明: 常见值 - 1=周期, 2=背景扫描, 3=自发, 6=激活, 7=激活确认, 8=停止激活, 9=停止激活确认");
    LOG_DEBUG(LOG_MODULE_NAME, "当前传送原因: %d", asdu->cause_of_transmission);
    offset += 2;
    
    /* 解析公共地址 */
    LOG_DEBUG(LOG_MODULE_NAME, "========== ASDU字节[%zu-%zu]: 公共地址 ==========", offset, offset+1);
    result = buffer_error_to_protocol_error(buffer_read_u16(buffer, offset, &asdu->common_address, 1)); /* 大端序 */
    if (result != PROTOCOL_SUCCESS) {
        return result;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "字节值: 0x%02X 0x%02X (%d)", 
             buffer[offset], buffer[offset+1], asdu->common_address);
    LOG_DEBUG(LOG_MODULE_NAME, "含义: 公共地址，2字节，大端序");
    LOG_DEBUG(LOG_MODULE_NAME, "说明: 标识ASDU的公共地址，通常为站地址或设备地址");
    LOG_DEBUG(LOG_MODULE_NAME, "当前公共地址: %d (0x%04X)", asdu->common_address, asdu->common_address);
    offset += 2;
    
    /* 设置ASDU长度 */
    asdu->length = buffer_size;
    
    /* 设置信息对象数据指针 */
    size_t info_object_size = buffer_size - ASDU_HEADER_SIZE;
    if (info_object_size > 0) {
        asdu->info_object_data = (uint8_t*)(buffer + offset);
    } else {
        asdu->info_object_data = NULL;
    }
    
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 解析完整ASDU
 * @details 解析完整的ASDU数据，包括头部和信息对象数据。函数会先解析
 *          ASDU头部，然后验证ASDU格式的正确性。这是ASDU解析的主要接口。
 * 
 * @param buffer 输入缓冲区，不能为NULL
 * @param buffer_size 缓冲区大小
 * @param asdu ASDU结构输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 解析成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 *         - PROTOCOL_ERROR_ASDU_INVALID_TYPE: 无效类型标识
 * 
 * @note 解析后的信息对象数据指针指向原始缓冲区
 * @warning 解析后的ASDU结构需要进一步解析信息对象数据
 * 
 * @see parse_asdu_header
 * @see validate_asdu
 * @see parse_single_point_asdu
 */
protocol_error_t parse_asdu(const uint8_t* buffer, size_t buffer_size, asdu_t* asdu) {
    if (buffer == NULL || asdu == NULL) {
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 解析ASDU头部 */
    protocol_error_t result = parse_asdu_header(buffer, buffer_size, asdu);
    if (result != PROTOCOL_SUCCESS) {
        return result;
    }
    
    /* 验证ASDU */
    return validate_asdu(asdu);
}

/* ==================== 遥信数据ASDU解析函数实现 ==================== */

/**
 * @brief 解析单点信息ASDU
 * @details 从ASDU中解析单点信息（遥信）数据。函数会验证ASDU类型标识、
 *          可变结构限定词等信息，然后提取单点信息对象数据。
 *          支持M_SP_NA_1、M_SP_TA_1等类型标识。
 * 
 * @param asdu ASDU结构指针，不能为NULL
 * @param info_objects 单点信息对象数组输出，不能为NULL
 * @param count 信息对象数量输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 解析成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_ASDU_INVALID_TYPE: 无效类型标识
 *         - PROTOCOL_ERROR_ASDU_INVALID_VSQ: 无效可变结构限定词
 *         - PROTOCOL_ERROR_ASDU_DATA_MISMATCH: 数据不匹配
 * 
 * @note 解析后的信息对象数据需要调用者处理
 * @warning 信息对象数组必须足够大以容纳所有数据
 * 
 * @see single_point_info_t
 * @see TYPE_ID_SINGLE_POINT
 * @see TYPE_ID_SINGLE_POINT_TIMESTAMP
 */
protocol_error_t parse_single_point_asdu(const asdu_t* asdu, single_point_info_t* info_objects, uint8_t* count) {
    LOG_DEBUG(LOG_MODULE_NAME, "解析单点信息ASDU: asdu=%p, info_objects=%p, count=%p", asdu, info_objects, count);
    
    if (asdu == NULL || info_objects == NULL || count == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 验证类型标识 */
    if (asdu->type_id != TYPE_ID_SINGLE_POINT && asdu->type_id != TYPE_ID_SINGLE_POINT_SOE) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的类型标识: %u，期望单点信息类型", asdu->type_id);
        return PROTOCOL_ERROR_ASDU_INVALID_TYPE;
    }
    
    /* 验证可变结构限定词 */
    if (asdu->vsq.sq != 0) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的可变结构限定词: sq=%u，期望0", asdu->vsq.sq);
        return PROTOCOL_ERROR_ASDU_INVALID_VSQ;
    }
    
    if (asdu->vsq.number_of_objects == 0) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的信息对象数量: %u，必须在1-127范围内", asdu->vsq.number_of_objects);
        return PROTOCOL_ERROR_ASDU_INVALID_VSQ;
    }
    
    /* 检查信息对象数据 */
    if (asdu->info_object_data == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU中没有信息对象数据");
        return PROTOCOL_ERROR_ASDU_DATA_MISMATCH;
    }
    
    size_t expected_size = asdu->vsq.number_of_objects * sizeof(single_point_info_t);
    size_t actual_size = asdu->length - ASDU_HEADER_SIZE;
    
    if (actual_size < expected_size) {
        LOG_ERROR(LOG_MODULE_NAME, "信息对象数据大小不匹配: 期望%zu字节，实际%zu字节", expected_size, actual_size);
        return PROTOCOL_ERROR_ASDU_DATA_MISMATCH;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "ASDU验证通过: type_id=%u, 对象数量=%u, 数据大小=%zu", 
              asdu->type_id, asdu->vsq.number_of_objects, actual_size);
    
    /* 复制信息对象数据 */
    memcpy(info_objects, asdu->info_object_data, expected_size);
    *count = asdu->vsq.number_of_objects;
    
    LOG_INFO(LOG_MODULE_NAME, "单点信息ASDU解析成功: type_id=%u, count=%u", asdu->type_id, *count);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 解析双点信息ASDU
 * @details 从ASDU中解析双点信息（遥信）数据。函数会验证ASDU类型标识、
 *          可变结构限定词等信息，然后提取双点信息对象数据。
 *          支持M_DP_NA_1、M_DP_TA_1等类型标识。
 * 
 * @param asdu ASDU结构指针，不能为NULL
 * @param info_objects 双点信息对象数组输出，不能为NULL
 * @param count 信息对象数量输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 解析成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_ASDU_INVALID_TYPE: 无效类型标识
 *         - PROTOCOL_ERROR_ASDU_INVALID_VSQ: 无效可变结构限定词
 *         - PROTOCOL_ERROR_ASDU_DATA_MISMATCH: 数据不匹配
 * 
 * @note 解析后的信息对象数据需要调用者处理
 * @warning 信息对象数组必须足够大以容纳所有数据
 * 
 * @see double_point_info_t
 * @see TYPE_ID_DOUBLE_POINT
 * @see TYPE_ID_DOUBLE_POINT_TIMESTAMP
 */
protocol_error_t parse_double_point_asdu(const asdu_t* asdu, double_point_info_t* info_objects, uint8_t* count) {
    LOG_DEBUG(LOG_MODULE_NAME, "解析双点信息ASDU: asdu=%p, info_objects=%p, count=%p", asdu, info_objects, count);
    
    if (asdu == NULL || info_objects == NULL || count == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 验证类型标识 */
    if (asdu->type_id != TYPE_ID_DOUBLE_POINT && asdu->type_id != TYPE_ID_DOUBLE_POINT_SOE) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的类型标识: %u，期望双点信息类型", asdu->type_id);
        return PROTOCOL_ERROR_ASDU_INVALID_TYPE;
    }
    
    /* 验证可变结构限定词 */
    if (asdu->vsq.sq != 0) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的可变结构限定词: sq=%u，期望0", asdu->vsq.sq);
        return PROTOCOL_ERROR_ASDU_INVALID_VSQ;
    }
    
    if (asdu->vsq.number_of_objects == 0) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的信息对象数量: %u，必须在1-127范围内", asdu->vsq.number_of_objects);
        return PROTOCOL_ERROR_ASDU_INVALID_VSQ;
    }
    
    /* 检查信息对象数据 */
    if (asdu->info_object_data == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU中没有信息对象数据");
        return PROTOCOL_ERROR_ASDU_DATA_MISMATCH;
    }
    
    size_t expected_size = asdu->vsq.number_of_objects * sizeof(double_point_info_t);
    size_t actual_size = asdu->length - ASDU_HEADER_SIZE;
    
    if (actual_size < expected_size) {
        LOG_ERROR(LOG_MODULE_NAME, "信息对象数据大小不匹配: 期望%zu字节，实际%zu字节", expected_size, actual_size);
        return PROTOCOL_ERROR_ASDU_DATA_MISMATCH;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "ASDU验证通过: type_id=%u, 对象数量=%u, 数据大小=%zu", 
              asdu->type_id, asdu->vsq.number_of_objects, actual_size);
    
    /* 复制信息对象数据 */
    memcpy(info_objects, asdu->info_object_data, expected_size);
    *count = asdu->vsq.number_of_objects;
    
    LOG_INFO(LOG_MODULE_NAME, "双点信息ASDU解析成功: type_id=%u, count=%u", asdu->type_id, *count);
    return PROTOCOL_SUCCESS;
}

/* ==================== 遥测数据ASDU解析函数实现 ==================== */

/**
 * @brief 解析测量值ASDU
 * @details 从ASDU中解析测量值（遥测）数据。函数会验证ASDU类型标识、
 *          可变结构限定词等信息，然后提取测量值信息对象数据。
 *          支持M_ME_NA_1、M_ME_NB_1、M_ME_NC_1等类型标识。
 * 
 * @param asdu ASDU结构指针，不能为NULL
 * @param info_objects 测量值信息对象数组输出，不能为NULL
 * @param count 信息对象数量输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 解析成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_ASDU_INVALID_TYPE: 无效类型标识
 *         - PROTOCOL_ERROR_ASDU_INVALID_VSQ: 无效可变结构限定词
 *         - PROTOCOL_ERROR_ASDU_DATA_MISMATCH: 数据不匹配
 * 
 * @note 解析后的信息对象数据需要调用者处理
 * @warning 信息对象数组必须足够大以容纳所有数据
 * 
 * @see measurement_info_t
 * @see TYPE_ID_MEASUREMENT_NORMALIZED
 * @see TYPE_ID_MEASUREMENT_SCALED
 * @see TYPE_ID_MEASUREMENT_SHORT_FLOAT
 */
protocol_error_t parse_measurement_asdu(const asdu_t* asdu, measurement_info_t* info_objects, uint8_t* count) {
    LOG_DEBUG(LOG_MODULE_NAME, "解析测量值ASDU: asdu=%p, info_objects=%p, count=%p", asdu, info_objects, count);
    
    if (asdu == NULL || info_objects == NULL || count == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 验证类型标识 */
    if (asdu->type_id != TYPE_ID_MEASUREMENT_NORMALIZED && 
        asdu->type_id != TYPE_ID_MEASUREMENT_SCALED && 
        asdu->type_id != TYPE_ID_MEASUREMENT_SHORT_FLOAT) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的类型标识: %u，期望测量值类型", asdu->type_id);
        return PROTOCOL_ERROR_ASDU_INVALID_TYPE;
    }
    
    /* 验证可变结构限定词 */
    if (asdu->vsq.sq != 0) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的可变结构限定词: sq=%u，期望0", asdu->vsq.sq);
        return PROTOCOL_ERROR_ASDU_INVALID_VSQ;
    }
    
    if (asdu->vsq.number_of_objects == 0) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的信息对象数量: %u，必须在1-127范围内", asdu->vsq.number_of_objects);
        return PROTOCOL_ERROR_ASDU_INVALID_VSQ;
    }
    
    /* 检查信息对象数据 */
    if (asdu->info_object_data == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU中没有信息对象数据");
        return PROTOCOL_ERROR_ASDU_DATA_MISMATCH;
    }
    
    size_t expected_size = asdu->vsq.number_of_objects * sizeof(measurement_info_t);
    size_t actual_size = asdu->length - ASDU_HEADER_SIZE;
    
    if (actual_size < expected_size) {
        LOG_ERROR(LOG_MODULE_NAME, "信息对象数据大小不匹配: 期望%zu字节，实际%zu字节", expected_size, actual_size);
        return PROTOCOL_ERROR_ASDU_DATA_MISMATCH;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "ASDU验证通过: type_id=%u, 对象数量=%u, 数据大小=%zu", 
              asdu->type_id, asdu->vsq.number_of_objects, actual_size);
    
    /* 复制信息对象数据 */
    memcpy(info_objects, asdu->info_object_data, expected_size);
    *count = asdu->vsq.number_of_objects;
    
    LOG_INFO(LOG_MODULE_NAME, "测量值ASDU解析成功: type_id=%u, count=%u", asdu->type_id, *count);
    return PROTOCOL_SUCCESS;
}

/* ==================== 控制命令ASDU解析函数实现 ==================== */

/**
 * @brief 解析单命令ASDU
 * @details 从ASDU中解析单命令（遥控）数据。函数会验证ASDU类型标识、
 *          可变结构限定词等信息，然后提取单命令信息对象数据。
 *          支持C_SC_NA_1类型标识。
 * 
 * @param asdu ASDU结构指针，不能为NULL
 * @param info_objects 单命令信息对象数组输出，不能为NULL
 * @param count 信息对象数量输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 解析成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_ASDU_INVALID_TYPE: 无效类型标识
 *         - PROTOCOL_ERROR_ASDU_INVALID_VSQ: 无效可变结构限定词
 *         - PROTOCOL_ERROR_ASDU_DATA_MISMATCH: 数据不匹配
 * 
 * @note 解析后的信息对象数据需要调用者处理
 * @warning 信息对象数组必须足够大以容纳所有数据
 * 
 * @see single_command_info_t
 * @see TYPE_ID_SINGLE_COMMAND
 * @see C_SC_NA_1
 */
protocol_error_t parse_single_command_asdu(const asdu_t* asdu, single_command_info_t* info_objects, uint8_t* count) {
    LOG_DEBUG(LOG_MODULE_NAME, "解析单点命令ASDU: asdu=%p, info_objects=%p, count=%p", asdu, info_objects, count);
    
    if (asdu == NULL || info_objects == NULL || count == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 验证类型标识 */
    if (asdu->type_id != TYPE_ID_SINGLE_COMMAND) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的类型标识: %u，期望单点命令类型", asdu->type_id);
        return PROTOCOL_ERROR_ASDU_INVALID_TYPE;
    }
    
    /* 验证可变结构限定词 */
    if (asdu->vsq.sq != 0) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的可变结构限定词: sq=%u，期望0", asdu->vsq.sq);
        return PROTOCOL_ERROR_ASDU_INVALID_VSQ;
    }
    
    if (asdu->vsq.number_of_objects == 0) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的信息对象数量: %u，必须在1-127范围内", asdu->vsq.number_of_objects);
        return PROTOCOL_ERROR_ASDU_INVALID_VSQ;
    }
    
    /* 检查信息对象数据 */
    if (asdu->info_object_data == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU中没有信息对象数据");
        return PROTOCOL_ERROR_ASDU_DATA_MISMATCH;
    }
    
    size_t expected_size = asdu->vsq.number_of_objects * sizeof(single_command_info_t);
    size_t actual_size = asdu->length - ASDU_HEADER_SIZE;
    
    if (actual_size < expected_size) {
        LOG_ERROR(LOG_MODULE_NAME, "信息对象数据大小不匹配: 期望%zu字节，实际%zu字节", expected_size, actual_size);
        return PROTOCOL_ERROR_ASDU_DATA_MISMATCH;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "ASDU验证通过: type_id=%u, 对象数量=%u, 数据大小=%zu", 
              asdu->type_id, asdu->vsq.number_of_objects, actual_size);
    
    /* 复制信息对象数据 */
    memcpy(info_objects, asdu->info_object_data, expected_size);
    *count = asdu->vsq.number_of_objects;
    
    LOG_INFO(LOG_MODULE_NAME, "单点命令ASDU解析成功: type_id=%u, count=%u", asdu->type_id, *count);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 解析双命令ASDU
 * @details 从ASDU中解析双命令（遥控）数据。函数会验证ASDU类型标识、
 *          可变结构限定词等信息，然后提取双命令信息对象数据。
 *          支持C_DC_NA_1类型标识。
 * 
 * @param asdu ASDU结构指针，不能为NULL
 * @param info_objects 双命令信息对象数组输出，不能为NULL
 * @param count 信息对象数量输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 解析成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_ASDU_INVALID_TYPE: 无效类型标识
 *         - PROTOCOL_ERROR_ASDU_INVALID_VSQ: 无效可变结构限定词
 *         - PROTOCOL_ERROR_ASDU_DATA_MISMATCH: 数据不匹配
 * 
 * @note 解析后的信息对象数据需要调用者处理
 * @warning 信息对象数组必须足够大以容纳所有数据
 * 
 * @see double_command_info_t
 * @see TYPE_ID_DOUBLE_COMMAND
 */
protocol_error_t parse_double_command_asdu(const asdu_t* asdu, double_command_info_t* info_objects, uint8_t* count) {
    LOG_DEBUG(LOG_MODULE_NAME, "解析双点命令ASDU: asdu=%p, info_objects=%p, count=%p", asdu, info_objects, count);
    
    if (asdu == NULL || info_objects == NULL || count == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 验证类型标识 */
    if (asdu->type_id != TYPE_ID_DOUBLE_COMMAND) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的类型标识: %u，期望双点命令类型", asdu->type_id);
        return PROTOCOL_ERROR_ASDU_INVALID_TYPE;
    }
    
    /* 验证可变结构限定词 */
    if (asdu->vsq.sq != 0) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的可变结构限定词: sq=%u，期望0", asdu->vsq.sq);
        return PROTOCOL_ERROR_ASDU_INVALID_VSQ;
    }
    
    if (asdu->vsq.number_of_objects == 0) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的信息对象数量: %u，必须在1-127范围内", asdu->vsq.number_of_objects);
        return PROTOCOL_ERROR_ASDU_INVALID_VSQ;
    }
    
    /* 检查信息对象数据 */
    if (asdu->info_object_data == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU中没有信息对象数据");
        return PROTOCOL_ERROR_ASDU_DATA_MISMATCH;
    }
    
    size_t expected_size = asdu->vsq.number_of_objects * sizeof(double_command_info_t);
    size_t actual_size = asdu->length - ASDU_HEADER_SIZE;
    
    if (actual_size < expected_size) {
        LOG_ERROR(LOG_MODULE_NAME, "信息对象数据大小不匹配: 期望%zu字节，实际%zu字节", expected_size, actual_size);
        return PROTOCOL_ERROR_ASDU_DATA_MISMATCH;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "ASDU验证通过: type_id=%u, 对象数量=%u, 数据大小=%zu", 
              asdu->type_id, asdu->vsq.number_of_objects, actual_size);
    
    /* 复制信息对象数据 */
    memcpy(info_objects, asdu->info_object_data, expected_size);
    *count = asdu->vsq.number_of_objects;
    
    LOG_INFO(LOG_MODULE_NAME, "双点命令ASDU解析成功: type_id=%u, count=%u", asdu->type_id, *count);
    return PROTOCOL_SUCCESS;
}

/* ==================== 系统命令ASDU解析函数实现 ==================== */

/**
 * @brief 解析总召唤ASDU
 * @details 从ASDU中解析总召唤数据。函数会验证ASDU类型标识、
 *          可变结构限定词等信息，然后提取QOI限定词。
 *          支持C_IC_NA_1类型标识。
 * 
 * @param asdu ASDU结构指针，不能为NULL
 * @param qoi QOI限定词输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 解析成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_ASDU_INVALID_TYPE: 无效类型标识
 *         - PROTOCOL_ERROR_ASDU_INVALID_VSQ: 无效可变结构限定词
 *         - PROTOCOL_ERROR_ASDU_DATA_MISMATCH: 数据不匹配
 * 
 * @note 解析后的QOI限定词需要调用者处理
 * @warning QOI必须是有效的限定词值
 * 
 * @see qoi_t
 * @see TYPE_ID_TOTAL_INTERROGATION
 * @see C_IC_NA_1
 */
protocol_error_t parse_total_interrogation_asdu(const asdu_t* asdu, qoi_t* qoi) {
    LOG_DEBUG(LOG_MODULE_NAME, "解析总召唤ASDU: asdu=%p, qoi=%p", asdu, qoi);
    
    if (asdu == NULL || qoi == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 验证类型标识 */
    if (asdu->type_id != TYPE_ID_TOTAL_INTERROGATION) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的类型标识: %u，期望总召唤类型", asdu->type_id);
        return PROTOCOL_ERROR_ASDU_INVALID_TYPE;
    }
    
    /* 验证可变结构限定词 */
    if (asdu->vsq.sq != 0) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的可变结构限定词: sq=%u，期望0", asdu->vsq.sq);
        return PROTOCOL_ERROR_ASDU_INVALID_VSQ;
    }
    
    if (asdu->vsq.number_of_objects != 1) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的信息对象数量: %u，期望1", asdu->vsq.number_of_objects);
        return PROTOCOL_ERROR_ASDU_INVALID_VSQ;
    }
    
    /* 检查信息对象数据 */
    if (asdu->info_object_data == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU中没有信息对象数据");
        return PROTOCOL_ERROR_ASDU_DATA_MISMATCH;
    }
    
    size_t expected_size = sizeof(qoi_t);
    size_t actual_size = asdu->length - ASDU_HEADER_SIZE;
    
    if (actual_size < expected_size) {
        LOG_ERROR(LOG_MODULE_NAME, "信息对象数据大小不匹配: 期望%zu字节，实际%zu字节", expected_size, actual_size);
        return PROTOCOL_ERROR_ASDU_DATA_MISMATCH;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "ASDU验证通过: type_id=%u, 数据大小=%zu", asdu->type_id, actual_size);
    
    /* 复制QOI数据 */
    memcpy(qoi, asdu->info_object_data, expected_size);
    
    LOG_INFO(LOG_MODULE_NAME, "总召唤ASDU解析成功: type_id=%u, qoi=%u", asdu->type_id, *qoi);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 解析时钟同步ASDU
 * @details 从ASDU中解析时钟同步数据。函数会验证ASDU类型标识、
 *          可变结构限定词等信息，然后提取时间戳数据。
 *          支持C_CS_NA_1类型标识。
 * 
 * @param asdu ASDU结构指针，不能为NULL
 * @param timestamp 时间戳输出，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 解析成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_ASDU_INVALID_TYPE: 无效类型标识
 *         - PROTOCOL_ERROR_ASDU_INVALID_VSQ: 无效可变结构限定词
 *         - PROTOCOL_ERROR_ASDU_DATA_MISMATCH: 数据不匹配
 * 
 * @note 解析后的时间戳数据需要调用者处理
 * @warning 时间戳必须是有效的CP56Time2a格式
 * 
 * @see cp56time2a_t
 * @see TYPE_ID_CLOCK_SYNC
 */
protocol_error_t parse_clock_sync_asdu(const asdu_t* asdu, cp56time2a_t* timestamp) {
    LOG_DEBUG(LOG_MODULE_NAME, "解析时钟同步ASDU: asdu=%p, timestamp=%p", asdu, timestamp);
    
    if (asdu == NULL || timestamp == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 验证类型标识 */
    if (asdu->type_id != TYPE_ID_CLOCK_SYNC) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的类型标识: %u，期望时钟同步类型", asdu->type_id);
        return PROTOCOL_ERROR_ASDU_INVALID_TYPE;
    }
    
    /* 验证可变结构限定词 */
    if (asdu->vsq.sq != 0) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的可变结构限定词: sq=%u，期望0", asdu->vsq.sq);
        return PROTOCOL_ERROR_ASDU_INVALID_VSQ;
    }
    
    if (asdu->vsq.number_of_objects != 1) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的信息对象数量: %u，期望1", asdu->vsq.number_of_objects);
        return PROTOCOL_ERROR_ASDU_INVALID_VSQ;
    }
    
    /* 检查信息对象数据 */
    if (asdu->info_object_data == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "ASDU中没有信息对象数据");
        return PROTOCOL_ERROR_ASDU_DATA_MISMATCH;
    }
    
    size_t expected_size = sizeof(cp56time2a_t);
    size_t actual_size = asdu->length - ASDU_HEADER_SIZE;
    
    if (actual_size < expected_size) {
        LOG_ERROR(LOG_MODULE_NAME, "信息对象数据大小不匹配: 期望%zu字节，实际%zu字节", expected_size, actual_size);
        return PROTOCOL_ERROR_ASDU_DATA_MISMATCH;
    }
    
    LOG_DEBUG(LOG_MODULE_NAME, "ASDU验证通过: type_id=%u, 数据大小=%zu", asdu->type_id, actual_size);
    
    /* 复制时间戳数据 */
    memcpy(timestamp, asdu->info_object_data, expected_size);
    
    /* 验证时间戳 */
    protocol_error_t result = validate_cp56time2a(timestamp);
    if (result != PROTOCOL_SUCCESS) {
        LOG_ERROR(LOG_MODULE_NAME, "时间戳验证失败: %d", result);
        return result;
    }
    
    LOG_INFO(LOG_MODULE_NAME, "时钟同步ASDU解析成功: type_id=%u", asdu->type_id);
    return PROTOCOL_SUCCESS;
}

/* ==================== ASDU验证函数实现 ==================== */

/**
 * @brief 验证ASDU类型
 * @details 验证ASDU的类型标识、传送原因、公共地址等基本字段的有效性。
 *          这是一个基础验证函数，用于检查ASDU的基本结构。
 * 
 * @param asdu ASDU结构指针，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 验证成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_ASDU_INVALID_TYPE: 无效类型标识
 *         - PROTOCOL_ERROR_ASDU_INVALID_COT: 无效传送原因
 *         - PROTOCOL_ERROR_ASDU_INVALID_ADDRESS: 无效公共地址
 * 
 * @note 验证包括类型标识、传送原因和公共地址
 * @warning 此函数只验证基本字段，不验证数据内容
 * 
 * @see is_type_id_valid
 * @see is_cause_of_transmission_valid
 * @see is_common_address_valid
 */
protocol_error_t validate_asdu_type(const asdu_t* asdu) {
    LOG_DEBUG(LOG_MODULE_NAME, "验证ASDU类型: asdu=%p", asdu);
    
    if (asdu == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 验证类型标识 */
    if (!is_type_id_valid(asdu->type_id)) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的类型标识: %u", asdu->type_id);
        return PROTOCOL_ERROR_ASDU_INVALID_TYPE;
    }
    
    /* 验证传送原因 */
    if (!is_cause_of_transmission_valid(asdu->cause_of_transmission)) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的传送原因: %u", asdu->cause_of_transmission);
        return PROTOCOL_ERROR_ASDU_INVALID_COT;
    }
    
    /* 验证公共地址 */
    if (!is_common_address_valid(asdu->common_address)) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的公共地址: %u", asdu->common_address);
        return PROTOCOL_ERROR_ASDU_INVALID_ADDRESS;
    }
    
    LOG_INFO(LOG_MODULE_NAME, "ASDU类型验证成功: type_id=%u, cot=%u, common_addr=%u", 
             asdu->type_id, asdu->cause_of_transmission, asdu->common_address);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 验证ASDU数据
 * @details 验证ASDU的数据部分，包括可变结构限定词和信息对象数据大小。
 *          这是一个数据验证函数，用于检查ASDU的数据完整性。
 * 
 * @param asdu ASDU结构指针，不能为NULL
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 验证成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_ASDU_INVALID_VSQ: 无效可变结构限定词
 *         - PROTOCOL_ERROR_ASDU_DATA_MISMATCH: 数据不匹配
 * 
 * @note 验证包括可变结构限定词和数据大小
 * @warning 此函数只验证数据部分，不验证头部字段
 * 
 * @see is_vsq_valid
 * @see calculate_asdu_info_object_size
 * @see ASDU_HEADER_SIZE
 */
protocol_error_t validate_asdu_data(const asdu_t* asdu) {
    LOG_DEBUG(LOG_MODULE_NAME, "验证ASDU数据: asdu=%p", asdu);
    
    if (asdu == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    /* 验证可变结构限定词 */
    if (!is_vsq_valid(*(uint8_t*)&asdu->vsq)) {
        LOG_ERROR(LOG_MODULE_NAME, "无效的可变结构限定词: sq=%u, number_of_objects=%u", 
                  asdu->vsq.sq, asdu->vsq.number_of_objects);
        return PROTOCOL_ERROR_ASDU_INVALID_VSQ;
    }
    
    /* 验证信息对象数据大小 */
    // TODO: 实现 calculate_asdu_info_object_size 函数
    // size_t expected_size = calculate_asdu_info_object_size(asdu);
    // size_t actual_size = asdu->length - ASDU_HEADER_SIZE;
    // 
    // if (actual_size != expected_size) {
    //     LOG_ERROR(LOG_MODULE_NAME, "信息对象数据大小不匹配: 期望%zu字节，实际%zu字节", expected_size, actual_size);
    //     return PROTOCOL_ERROR_ASDU_DATA_MISMATCH;
    // }
    
    LOG_INFO(LOG_MODULE_NAME, "ASDU数据验证成功: type_id=%u, vsq=%u, length=%u", 
             asdu->type_id, asdu->vsq.number_of_objects, asdu->length);
    return PROTOCOL_SUCCESS;
}

/* ==================== 遥测值计算函数实现 ==================== */

/**
 * @brief 计算遥测值
 * @details 根据协议规范计算遥测显示值：显示值 = 满量程值 × 原始值 / 32767
 * 
 * @param raw_value 原始值 (0-32767)
 * @param full_scale 满量程值
 * @return 计算后的显示值
 */
float calculate_measured_value(uint16_t raw_value, float full_scale) {
    return (full_scale * raw_value) / 32767.0f;
}

/**
 * @brief 解析遥测值
 * @details 从缓冲区中解析遥测值并计算显示值
 * 
 * @param buffer 输入缓冲区，不能为NULL
 * @param offset 偏移量
 * @param full_scale 满量程值
 * @param result 输出结果，不能为NULL
 * @return 协议错误码
 */
protocol_error_t parse_measured_value(const uint8_t* buffer, size_t buffer_size, size_t offset, 
                                     float full_scale, float* result) {
    if (buffer == NULL || result == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    if (offset + 2 > buffer_size) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小，无法读取遥测值");
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    // 读取原始值（2字节，低字节在前）
    uint16_t raw_value = buffer[offset] | (buffer[offset + 1] << 8);
    
    // 计算显示值
    *result = calculate_measured_value(raw_value, full_scale);
    
    LOG_DEBUG(LOG_MODULE_NAME, "遥测值解析: 原始值=%u, 满量程=%.2f, 显示值=%.2f", 
              raw_value, full_scale, *result);
    
    return PROTOCOL_SUCCESS;
}

/* ==================== ASDU信息提取函数实现 ==================== */

/**
 * @brief 获取ASDU类型描述
 * @details 根据ASDU的类型标识字段获取对应的中文描述。
 *          用于调试和日志记录，便于理解ASDU的数据类型。
 * 
 * @param asdu ASDU结构指针，不能为NULL
 * @param description 描述字符串输出缓冲区，不能为NULL
 * @param description_size 缓冲区大小
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 获取成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 * 
 * @note 描述字符串会自动截断以适配缓冲区大小
 * @warning 缓冲区必须足够大以容纳描述字符串
 * 
 * @see type_id_t
 * @see TYPE_ID_SINGLE_POINT
 * @see TYPE_ID_DOUBLE_POINT
 * @see TYPE_ID_MEASUREMENT_NORMALIZED
 */
protocol_error_t get_asdu_type_description(const asdu_t* asdu, char* description, size_t description_size) {
    LOG_DEBUG(LOG_MODULE_NAME, "获取ASDU类型描述: asdu=%p, description=%p, description_size=%zu", 
              asdu, description, description_size);
    
    if (asdu == NULL || description == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    if (description_size == 0) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: description_size=%zu", description_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    const char* type_desc = "未知类型";
    
    switch (asdu->type_id) {
        case TYPE_ID_SINGLE_POINT:
            type_desc = "单点信息";
            break;
        case TYPE_ID_DOUBLE_POINT:
            type_desc = "双点信息";
            break;
        case TYPE_ID_MEASUREMENT_NORMALIZED:
            type_desc = "测量值(归一化)";
            break;
        case TYPE_ID_MEASUREMENT_SCALED:
            type_desc = "测量值(标度化)";
            break;
        case TYPE_ID_MEASUREMENT_SHORT_FLOAT:
            type_desc = "测量值(短浮点)";
            break;
        case TYPE_ID_SINGLE_COMMAND:
            type_desc = "单点命令";
            break;
        case TYPE_ID_DOUBLE_COMMAND:
            type_desc = "双点命令";
            break;
        case TYPE_ID_TOTAL_INTERROGATION:
            type_desc = "总召唤命令";
            break;
        case TYPE_ID_CLOCK_SYNC:
            type_desc = "时钟同步命令";
            break;
        default:
            type_desc = "其他类型";
            break;
    }
    
    strncpy(description, type_desc, description_size - 1);
    description[description_size - 1] = '\0';
    
    LOG_INFO(LOG_MODULE_NAME, "获取ASDU类型描述成功: type_id=%u, description=%s", asdu->type_id, description);
    return PROTOCOL_SUCCESS;
}

/**
 * @brief 获取ASDU传送原因描述
 * @details 根据ASDU的传送原因字段获取对应的中文描述。
 *          用于调试和日志记录，便于理解ASDU的传输目的。
 * 
 * @param asdu ASDU结构指针，不能为NULL
 * @param description 描述字符串输出缓冲区，不能为NULL
 * @param description_size 缓冲区大小
 * @return 协议错误码
 *         - PROTOCOL_SUCCESS: 获取成功
 *         - PROTOCOL_ERROR_NULL_POINTER: 空指针错误
 *         - PROTOCOL_ERROR_BUFFER_TOO_SMALL: 缓冲区太小
 * 
 * @note 描述字符串会自动截断以适配缓冲区大小
 * @warning 缓冲区必须足够大以容纳描述字符串
 * 
 * @see cause_of_transmission_t
 * @see COT_PERIODIC
 * @see COT_SPONTANEOUS
 * @see COT_REQUEST
 */
protocol_error_t get_asdu_cause_description(const asdu_t* asdu, char* description, size_t description_size) {
    LOG_DEBUG(LOG_MODULE_NAME, "获取ASDU传送原因描述: asdu=%p, description=%p, description_size=%zu", 
              asdu, description, description_size);
    
    if (asdu == NULL || description == NULL) {
        LOG_ERROR(LOG_MODULE_NAME, "空指针参数错误");
        return PROTOCOL_ERROR_NULL_POINTER;
    }
    
    if (description_size == 0) {
        LOG_ERROR(LOG_MODULE_NAME, "缓冲区太小: description_size=%zu", description_size);
        return PROTOCOL_ERROR_BUFFER_TOO_SMALL;
    }
    
    const char* cause_desc = "未知原因";
    
    switch (asdu->cause_of_transmission) {
        case COT_PERIODIC:
            cause_desc = "周期/循环";
            break;
        case COT_BACKGROUND_SCAN:
            cause_desc = "背景扫描";
            break;
        case COT_SPONTANEOUS:
            cause_desc = "突发(自发)";
            break;
        case COT_INITIALIZATION:
            cause_desc = "初始化";
            break;
        case COT_REQUEST:
            cause_desc = "请求/被请求";
            break;
        case COT_ACTIVATION:
            cause_desc = "激活";
            break;
        case COT_ACTIVATION_CONFIRM:
            cause_desc = "激活确认";
            break;
        case COT_DEACTIVATION:
            cause_desc = "停止激活";
            break;
        case COT_DEACTIVATION_CONFIRM:
            cause_desc = "停止激活确认";
            break;
        case COT_ACTIVATION_TERMINATION:
            cause_desc = "激活终止";
            break;
        default:
            cause_desc = "其他原因";
            break;
    }
    
    strncpy(description, cause_desc, description_size - 1);
    description[description_size - 1] = '\0';
    
    LOG_INFO(LOG_MODULE_NAME, "获取ASDU传送原因描述成功: cot=%u, description=%s", asdu->cause_of_transmission, description);
    return PROTOCOL_SUCCESS;
}
